using System;
using System.Collections.Generic;
using System.Text;

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

using HadronData;

namespace Hadron.Entities
{
    class Fighter
        : Entity
    {
        private static Polygon s_polygonContact, s_polygonVisible;

        private float m_fReload;
        private bool m_bMissile;
        private Polygon m_polygonContact, m_polygonVisible;

        public Fighter(EntityMarker p_entityMarker, Environment p_environment, bool p_bMissile)
            : base(p_entityMarker, p_environment)
        {
            // construct geometry
            if (s_polygonVisible == null)
            {
                s_polygonVisible = new Polygon();

                s_polygonVisible.Edges.Add(new Edge(-16.0f, -4.0f, -16.0f, 4.0f));

                s_polygonVisible.Edges.Add(new Edge(-16.0f, -4.0f, -12.0f, -16.0f));
                s_polygonVisible.Edges.Add(new Edge(-16.0f, 4.0f, -12.0f, 16.0f));

                s_polygonVisible.Edges.Add(new Edge(-12.0f, -16.0f, -4.0f, -16.0f));
                s_polygonVisible.Edges.Add(new Edge(-12.0f, 16.0f, -4.0f, 16.0f));

                s_polygonVisible.Edges.Add(new Edge(-4.0f, -16.0f, 2.0f, -8.0f));
                s_polygonVisible.Edges.Add(new Edge(-4.0f, 16.0f, 2.0f, 8.0f));

                s_polygonVisible.Edges.Add(new Edge(2.0f, -8.0f, 16.0f, -4.0f));
                s_polygonVisible.Edges.Add(new Edge(2.0f, 8.0f, 16.0f, 4.0f));

                s_polygonVisible.Edges.Add(new Edge(16.0f, -4.0f, 6.0f, -4.0f));
                s_polygonVisible.Edges.Add(new Edge(16.0f, 4.0f, 6.0f, 4.0f));

                s_polygonVisible.Edges.Add(new Edge(6.0f, -4.0f, 6.0f, 4.0f));

                s_polygonContact = new Polygon(s_polygonVisible);

                s_polygonVisible.Edges.Add(new Edge(-10.0f, 0.0f, -4.0f, -4.0f, Color.YellowGreen));
                s_polygonVisible.Edges.Add(new Edge(-10.0f, 0.0f, -4.0f, 4.0f, Color.YellowGreen));

                s_polygonVisible.Edges.Add(new Edge(-4.0f, -4.0f, 0.0f, -4.0f, Color.YellowGreen));
                s_polygonVisible.Edges.Add(new Edge(-4.0f, 4.0f, 0.0f, 4.0f, Color.YellowGreen));

                s_polygonVisible.Edges.Add(new Edge(0.0f, -4.0f, 2.0f, 0.0f, Color.YellowGreen));
                s_polygonVisible.Edges.Add(new Edge(0.0f, 4.0f, 2.0f, 0.0f, Color.YellowGreen));
            }

            m_bMissile = p_bMissile;
            m_fReload = 0.0f;
            m_nHealth = m_bMissile ? 7 : 4;
            m_nPoints = m_bMissile ? 1000 : 400;

            m_polygonContact = new Polygon(s_polygonContact);
            m_polygonContact.Transform(m_trnPlacement);

            m_polygonVisible = new Polygon(s_polygonVisible);
            m_polygonVisible.Transform(m_trnPlacement);

            Color colourHull = p_bMissile ? Color.OrangeRed : new Color(0, 128, 255);
            for (int nIndex = 0; nIndex < s_polygonContact.Edges.Count; nIndex++)
                m_polygonVisible.Edges[nIndex].Colour = colourHull;

            m_circleBounds = s_polygonContact.GetBoundingCircle(Vector2.Zero);
        }

        public override void Update(GameTime p_gameTime)
        {
            float fDeltaTime = (float)p_gameTime.ElapsedGameTime.TotalSeconds;

            Vector2 vecOffset = m_environment.PlayerShip.Position - Position;
            Vector2 vecDirection = vecOffset;
            vecDirection.Normalize();
            m_trnPlacement.RotationDirection = vecDirection;

            float fAttackDistance = m_bMissile ? 192.0f : 128.0f;
            float fDistance = Vector2.Dot(vecOffset, vecDirection);
            if (fAttackDistance < fDistance * 0.9f)
                m_vecVelocity = vecDirection * 32.0f;
            else if (fAttackDistance > fDistance * 1.1f)
                m_vecVelocity = vecDirection * -32.0f;
            else
                m_vecVelocity = new Vector2(-vecDirection.Y, vecDirection.X) * 32.0f;

            m_trnPlacement.Translation += m_vecVelocity * fDeltaTime;

            m_circleBounds.Centre = m_trnPlacement.Translation;

            m_fReload -= fDeltaTime;
            if (m_fReload <= 0.0f)
            {
                Vector2 vecProjectilePosition = m_trnPlacement.Apply(new Vector2(16.0f, 0.0f));
                EnemyPlasma enemyPlasma = new EnemyPlasma(
                    m_environment, m_bMissile, vecProjectilePosition);

                enemyPlasma.Position = vecProjectilePosition;
                Vector2 vecVelocity = m_trnPlacement.RotationDirection * 64.0f;
                enemyPlasma.Velocity = vecVelocity;
                m_environment.EnemyProjectiles.Add(enemyPlasma);
                m_fReload += 3.0f;
            }

            m_polygonContact.Transform(m_trnPlacement, s_polygonContact);
            m_polygonVisible.Transform(m_trnPlacement, s_polygonVisible);

            // collisions with level
            Level level = m_environment.CurrentLevel;
            List<ContactPoint> listContactPoints = new List<ContactPoint>();
            level.ComputeContactPoints(m_polygonContact, listContactPoints);
            foreach (ContactPoint contactPoint in listContactPoints)
                m_trnPlacement.Translation += contactPoint.Normal * 0.5f;
        }

        public override void Draw(SpriteBatch p_spriteBatch)
        {
            m_polygonVisible.Draw(p_spriteBatch);
        }

        public override EntityType Type
        {
            get { return EntityType.Drone; }
        }

        public override bool Destructuble
        {
            get { return true; }
        }

        public override bool Hostile
        {
            get { return true; }
        }

        public override Geometry Geometry
        {
            get { return m_polygonContact; }
        }
    }
}
